<?php
/**
* Error reporting: collect and report in a good fashion any error!.
*<p>A custom error handler is registered for both Exceptions and traditional PHP errors.</p>
*<p>This error handler job is to collect all the most significant informations on the environment
*and program state when the error occurred and report them both via echo to the screen (then redirected by
*the output buffering to the user-define error callback) and via email to the webaster.</p>
*@package Core
*@subpackage ErrorReporting
*@author Willy Gardiol <willy@gardiol.org>
*@version 1.0
*/

/**
* Collect all enviroment info and send an error report.
*<p>This error handler job is to collect all the most significant informations on the environment
*and program state when the error occurred and report them both via echo to the screen (then redirected by
*the output buffering to the user-define error callback) and via email to the webaster.</p>
*@return nil No return value: the function do an exit(0) at the end.
*@param int $errno Number of error
*@param string $errmsg Error message
*@param string $filename Filename where error occurred
*@param int $linenum Line number where error occurred
*@param array $context Optional call trace
*/
function ReportErrorMessage( $errno, $errmsg, $filename, $linenum, $context, $traces = false )
{
	global $error_reporting_style;
	static $count = 0;
	if ( $count++ > 5 )
		echo "Maximum error count reached!";
	else
	{
		# Loop prevnetion, disable all errors in this handler...
	#	error_reporting(0);
	
		if ( $traces === false )
			$traces = debug_backtrace();
	
		# A full debug message is composed of the following blocks:
		# - error_msg (always printed)
		# - user_info (always printed)
		# - internals (printed only if debug=true)
		# - backtrace (printed only if debug=true)
		# All blocks are always emailed to the error_email destination.
	
		# Prepare the debug statement to be displayed!
		$error_msg = "An error has occured: ";
		$error_msg .= "<p class='error_p'>$errmsg ($errno)</p>";
		$error_msg .= "At position: <p class='error_p'>$filename, $linenum.</p>";	
	
		# Format some additional data to be sent
		$user_info = "\n***************************************\n";
		$user_info .= "**** User info: ".$_SERVER['HTTP_USER_AGENT'] . "\n";
		$user_info .= "**** Remote address: ".$_SERVER['REMOTE_ADDR'] . "\n";
		$user_info .= "**** Referer (approx.): ";
		$user_info .= isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : "-none-";
		$user_info .= "\n";
		$dt = getdate();
		$user_info .= "**** Current date/time: ";
		$user_info .= $dt["mday"]."/".$dt["month"]."/".$dt["year"]." - ".$dt["hours"].":".$dt["minutes"].":".$dt["seconds"]."\n";
	
		$internals = "***************************************\n";
		$internals .= "**** GET PARAMS: ".var_export( Core::GetDump(), true)."\n";
		$internals .= "**** POST PARAMS: ".var_export( Core::PostDump(), true)."\n";
		$internals .= "***************************************\n";
	
		if ( isset( $_GET ) )
			foreach ( $_GET as $key => $get )
				$internals .= "**** GET '$key': ".$get."\n";
		if ( isset( $_POST ) )
			foreach ( $_POST as $key => $post )
				$internals .= "**** POST '$key': ".$post."\n";
		if ( isset( $_SESSION ) )
			foreach ( $_SESSION as $key => $sess )
				$internals .= "**** SESSION '$key': ".$sess."\n";
		$internals .= "***************************************\n";
	
		# Print backtrace
		$backtrace = "\n***************************************\n";
		$backtrace .= "**** BACKTRACE IS:\n";
		foreach ( $traces as $trace )
		{
			$file = isset( $trace["file"] ) ? $trace["file"] : "<no file>";
			$line = isset( $trace["line"] ) ? $trace["line"] : "-1";
			$function = isset( $trace["function"] ) ? $trace["function"] : "<unknown>";
			if ( $function != "ReportErrorMessage" )
			{
				$args = isset( $trace["args"] ) ? print_r($trace["args"], true) : "";
				$args = str_replace("\n", " ",$args);
				$backtrace .= "**** $file($line): $function() -> $args <-\n\n";
			}
		}
		$backtrace .= "***************************************\n";
		
		$error_string = "";
		$error_string .= $error_reporting_style == "html" ?  "<p><b>" : "";
		$error_string .= $error_msg;
		$error_string .= $error_reporting_style == "html" ?  "</b></p><pre>": "\n";
		$error_string .= $user_info;
		if ( Core::GetConfig("error_debug") )
		{
			$error_string .= $error_reporting_style == "html" ? "" : "\n";
			$error_string .= $internals;
			$error_string .= $error_reporting_style == "html" ? "" : "\n";
			$error_string .= $backtrace;
		}
		$error_string .= $error_reporting_style == "html" ? "</pre>" : "\n";
		echo $error_string;
		if ( ($error_mail = Core::GetConfig("webmaster")) !== false )
		{
			$tmp = preg_split( "/(\/*.*\/)(.*?)(\.php)?(\??.*$)/",$_SERVER["REQUEST_URI"], -1, PREG_SPLIT_DELIM_CAPTURE );
			$server = $tmp[0];
	
			$subject = "Error for $server! - $errmsg ($errno)";
			$message = "An error has occurred on server '$server'.\n
					The error is: '$errmsg', ($errno)\n
					On file '$filename', at line '$linenum'\n\n\n".$user_info.$internals.$backtrace;
			$headers = "From: $error_mail\n";
			$headers .= "X-Mailer: PHP Web Autobot\n";
			mail( $error_mail, $subject, $message,$headers );
		}
	}
	exit();
}

/**
* The Exception error handler: remap the exception error and call the error report function
*@param Exception $exception The exception to report
*/
function exception_handler( $exception )
{
	ReportErrorMessage( $exception->getCode(),
						$exception->getMessage(),
						$exception->getFile(),
						$exception->getLine(),
						false,
						$exception->getTrace() );
}


// set_error_handler(create_function('$a,$b,$c,$d','throw new ErrorException($b,0,$a,$c,$d);'),E_ALL);
set_exception_handler("exception_handler");
set_error_handler("ReportErrorMessage");

if ( Core::GetConfig("error_debug") )
	error_reporting( E_ALL );
else
	error_reporting( E_ERROR | E_WARNING | E_PARSE | E_NOTICE );
?>
